#include "stdafx.h"
#include "swf/swf.hpp"

namespace xm
{
	struct FMT_ASPD
	{
		FileType				fmtid;
		CreateAttachStreamPtr	handler;
	};

	FMT_ASPD gAspTable [] = 
	{
		{ FMT_SWX,	DecodeSWx },	
	};

	HRESULT XmCreateAttachStream( FMTID fmt, IUnknown * insp, IKBStream** ppstm )
	{
		iptr<IKBStream> sp(insp);
		if( !sp ) return E_NOINTERFACE;
		for( size_t i = 0; i < sizeof(gAspTable)/sizeof(gAspTable[0]); ++i )
		{
			if( fmt != gAspTable[i].fmtid ) continue;
			return gAspTable[i].handler( sp, ppstm );
		}
		return E_FAIL;
	}
	//////////////////////////////////////////////////////////////////////////
	HRESULT DecodeSWx( IKBStream * pstm, IKBStream ** ppstm )
	{
		swf::BxStream wrapper(pstm);
		swf::StreamIn ins(&wrapper);
		swf::FileHeader hdr;
		if( !hdr.read( ins ) ) return E_FAIL;
		if( hdr.sig0 == 'F' ) 
		{
			*ppstm = pstm; pstm->AddRef();
			return S_OK;
		}

		iptr<IKBCoderLL> infalte( hdr.sig0 == 'C' ? "InflateCoderLL" : "LzmaDecoderLL" );
		if( !infalte ) return E_FAIL;

		iptr<IKVirtalFile> tmp( "VirtualFile" );
		iptr<IKBStream> tmps(tmp);
		tmps->SetPos(8);
		CodeToStream wch(tmps);
		RFAILED( CodeTo<0x2000>( infalte, pstm, hdr.length, &wch ) );
		uint64_t fs = tmps->Length();
		if( fs == LENGTH_ERROR ) return E_FAIL;
		hdr.sig0 = 'F';
		hdr.length = (uint32_t)fs;

		SIZE_T eff = 0;
		RFAILED( tmps->Writep(0,&hdr,sizeof(hdr),&eff) );

		if( eff != sizeof(hdr) ) return E_FAIL;

		tmps->SetPos(0);

		*ppstm = tmps.detach();
		
		return S_OK;
	}
};